#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include <psp2/ctrl.h>
#include <psp2/power.h>
#include <psp2/system_param.h>
#include <psp2/kernel/processmgr.h>

#include <vita2d.h>
#include "vita2d_ext.h"

#include "ui.h"
#include "utils.h"
#include "menu.h"
#include "browser.h"
#include "about.h"
#include "shaders.h"
#include "config.h"
#include "init.h"
#include "retro.h"
#include "video.h"
#include "lang.h"
#include "boot.h"

// Main
#define MAIN_PADDING 0.0f

#define STATUS_BAR_PADDING_T 10.0f
#define STATUS_BAR_PADDING_L 10.0f

// Scroll bar
#define SCROLL_BAR_MIN_HEIGHT 4.0f
#define SCROLL_BAR_COLOR COLOR_ALPHA(LITEGRAY, 0x8F)
#define SCROLL_BAR_BG_COLOR COLOR_ALPHA(DARKGRAY, 0xAF)

#define MAIN_TITLE APP_NAME_STR " v" APP_VER_STR

char STR_BUTTON_ENTER[4], STR_BUTTON_CANCEL[4];

vita2d_texture *wallpaper_tex = NULL;
vita2d_texture *splash_tex = NULL;
float wallpaper_x_scale, wallpaper_y_scale;
float splash_x_scale, splash_y_scale;

static float status_bar_width, status_bar_height;

// Main free draw
float MAIN_FREE_DRAW_PADDING_T = 10.0f;
float MAIN_FREE_DRAW_PADDING_L = 10.0f;
float MAIN_FREE_DRAW_WIDTH, MAIN_FREE_DRAW_HEIGHT;
float MAIN_FREE_DRAW_SX, MAIN_FREE_DRAW_DX, MAIN_FREE_DRAW_SY, MAIN_FREE_DRAW_DY;

extern InstructionsEntry browser_instructions_entries[];
extern InstructionsEntry about_instructions_entries[];
extern int about_open;
extern int menu_open;

static void initUiDrawInfo()
{
    float line_height = UiGetLineHeight();

    status_bar_width = SCREEN_WIDTH;
    status_bar_height = STATUS_BAR_PADDING_T * 2 + line_height;

    MAIN_FREE_DRAW_WIDTH = SCREEN_WIDTH - MAIN_PADDING * 2 - MAIN_FREE_DRAW_PADDING_T * 2;
    MAIN_FREE_DRAW_HEIGHT = SCREEN_HEIGHT - MAIN_PADDING * 2 - status_bar_height * 2 - MAIN_FREE_DRAW_PADDING_T * 2;
    MAIN_FREE_DRAW_SX = MAIN_PADDING + MAIN_FREE_DRAW_PADDING_L;
    MAIN_FREE_DRAW_DX = MAIN_FREE_DRAW_SX + MAIN_FREE_DRAW_WIDTH;
    MAIN_FREE_DRAW_SY = MAIN_PADDING + status_bar_height + MAIN_FREE_DRAW_PADDING_T;
    MAIN_FREE_DRAW_DY = SCREEN_HEIGHT - MAIN_PADDING - status_bar_height - MAIN_FREE_DRAW_PADDING_T;
}

static void initButtonStr()
{
    if (enter_button == SCE_SYSTEM_PARAM_ENTER_BUTTON_CIRCLE)
    {
        strcpy(STR_BUTTON_ENTER, STR_BUTTON_CIRCLE);
        strcpy(STR_BUTTON_CANCEL, STR_BUTTON_CROSS);
    }
    else
    {
        strcpy(STR_BUTTON_ENTER, STR_BUTTON_CROSS);
        strcpy(STR_BUTTON_CANCEL, STR_BUTTON_CIRCLE);
    }
}

static int InitImagesThreadCallback(SceSize args, void *argp)
{
    vita2d_texture *texture = NULL;
    char path[MAX_PATH_LENGTH];

    if (private_assets_dir)
    {
        snprintf(path, MAX_PATH_LENGTH, "%s/%s", private_assets_dir, WALLPAPER_PNG_NAME);
        texture = vita2d_load_PNG_file(path);
    }
    if (!texture)
    {
        snprintf(path, MAX_PATH_LENGTH, "%s/%s", public_assets_dir, WALLPAPER_PNG_NAME);
        texture = vita2d_load_PNG_file(path);
    }
    if (texture)
    {
        wallpaper_x_scale = SCREEN_WIDTH / (float)vita2d_texture_get_width(texture);
        wallpaper_y_scale = SCREEN_HEIGHT / (float)vita2d_texture_get_height(texture);
        wallpaper_tex = texture;
    }

    texture = NULL;
    if (private_assets_dir)
    {
        snprintf(path, MAX_PATH_LENGTH, "%s/%s", private_assets_dir, SPLASH_PNG_NAME);
        texture = vita2d_load_PNG_file(path);
    }
    if (!texture)
    {
        snprintf(path, MAX_PATH_LENGTH, "%s/%s", public_assets_dir, SPLASH_PNG_NAME);
        texture = vita2d_load_PNG_file(path);
    }
    if (texture)
    {
        splash_x_scale = SCREEN_WIDTH / (float)vita2d_texture_get_width(texture);
        splash_y_scale = SCREEN_HEIGHT / (float)vita2d_texture_get_height(texture);
        splash_tex = texture;
    }

    sceKernelExitDeleteThread(0);
    return 0;
}

void initImagesThread()
{
    SceUID thid = sceKernelCreateThread("init_images_thread", InitImagesThreadCallback, 0x10000100, 0x10000, 0, 0, NULL);
    if (thid >= 0)
        sceKernelStartThread(thid, 0, NULL);
}

static void finishImages()
{
    if (wallpaper_tex)
    {
        vita2d_free_texture(wallpaper_tex);
        wallpaper_tex = NULL;
    }

    if (splash_tex)
    {
        vita2d_free_texture(splash_tex);
        splash_tex = NULL;
    }
}

void initDrawInfo()
{
    initUiDrawInfo();
    initBrowserDrawInfo();
    initAboutDrawInfo();
    initMenuDrawInfo();
}

void initUi()
{
    initImagesThread();
    initFonts();
    initButtonStr();
    initDrawInfo();
    initShaders();
    initBrowser();
}

void finishUi()
{
    finishFonts();
    finishImages();
    finishShaders();
}

static void drawTopStatusBar(char *title)
{
    float view_sx = 0;
    float view_dx = SCREEN_WIDTH;
    float view_sy = 0;

    vita2d_draw_rectangle(view_sx, view_sy, status_bar_width, status_bar_height, DEFALUT_BG_COLOR);

    float sx = view_sx + STATUS_BAR_PADDING_L;
    float sy = view_sy + STATUS_BAR_PADDING_T;
    UiDrawText(sx, sy, WHITE, title);

    sx = view_dx - STATUS_BAR_PADDING_L;
    if (!is_vitatv_model)
    {
        uint32_t color;
        if (scePowerIsBatteryCharging())
            color = YELLOW;
        else if (scePowerIsLowBattery())
            color = RED;
        else
            color = GREEN;

        int percent = scePowerGetBatteryLifePercent();
        char battery_string[24];
        snprintf(battery_string, sizeof(battery_string), "%s: %d%%", STR_BATTERY, percent);
        float battery_x = sx - UiGetTextWidth(battery_string);
        UiDrawText(battery_x, sy, color, battery_string);
        sx = battery_x - STATUS_BAR_PADDING_L;
    }

    // Date & time
    SceDateTime time;
    sceRtcGetCurrentClock(&time, 0);

    char date_string[24];
    getDateString(date_string, date_format, &time);

    char time_string[16];
    getTimeString(time_string, time_format, &time);

    char string[64];
    snprintf(string, sizeof(string), "%s  %s", date_string, time_string);
    float date_time_x = sx - UiGetTextWidth(string);
    UiDrawText(date_time_x, sy, DEFALUT_FONT_COLOR, string);
}

static void drawBottomStatusBar(InstructionsEntry *entries)
{
    float view_sx = 0;
    float view_sy = SCREEN_HEIGHT - status_bar_height;

    vita2d_draw_rectangle(view_sx, view_sy, status_bar_width, status_bar_height, DEFALUT_BG_COLOR);

    float sx = view_sx + STATUS_BAR_PADDING_L;
    float sy = view_sy + STATUS_BAR_PADDING_T;
    int i, j;
    for (i = 0; entries[i].instruction; i++)
    {
        for (j = 0; entries[i].buttons[j]; j++)
        {
            sx += UiDrawText(sx, sy, AZURE, entries[i].buttons[j]);
        }
        sx += UiDrawText(sx, sy, AZURE, ":");
        sx += UiDrawText(sx, sy, WHITE, entries[i].instruction);
        sx += STATUS_BAR_PADDING_L;
    }
}

void drawScrollBar(float sx, float sy, float full_height, int max_lines, int list_len, int top_pos)
{
    if (list_len > max_lines)
    {
        // vita2d_draw_rectangle(sx, sy, SCROLL_BAR_WIDTH, full_height, SCROLL_BAR_BG_COLOR);

        float pcs_height = full_height / list_len;
        float scroll_bar_sy = sy + top_pos * pcs_height;
        float scroll_bar_height = max_lines * pcs_height;
        vita2d_draw_rectangle(sx, MIN(scroll_bar_sy, (sy + full_height - scroll_bar_height)), SCROLL_BAR_WIDTH,
                              MAX(scroll_bar_height, SCROLL_BAR_MIN_HEIGHT), SCROLL_BAR_COLOR);
    }
}

void printSafeMode()
{
    while (1)
    {
        while (1)
        {
            int x = 30, y = 30;
            float line_height = UiGetLineHeight();
            UiStartDrawing();
            UiDrawText(x, y, WHITE, STR_SAFE_MODE_PRINT_0);
            y += line_height;
            UiDrawText(x, y, WHITE, STR_SAFE_MODE_PRINT_1);
            y += line_height * 2;
            UiDrawText(x, y, WHITE, STR_SAFE_MODE_PRINT_2);
            UiEndDrawing();

            SceCtrlData pad;
            memset(&pad, 0, sizeof(SceCtrlData));
            sceCtrlPeekBufferPositiveExt2(0, &pad, 1);

            if (pad.buttons & ~SCE_CTRL_INTERCEPTED)
                break;
        }
        finishMain();
        sceKernelExitProcess(0);
    }
}

void printSplash()
{
    UiStartDrawing();
    if (splash_tex)
        vita2d_draw_texture_scale(splash_tex, 0.0f, 0.0f, splash_x_scale, splash_y_scale);
    UiEndDrawing();
}

void UiDrawMain()
{
    if (game_loaded)
    {
        vitaVideoDrawFrame();
    }
    else
    {
        if (wallpaper_tex)
            vita2d_draw_texture_scale(wallpaper_tex, 0.0f, 0.0f, wallpaper_x_scale, wallpaper_y_scale);

        char title[256];
        InstructionsEntry *instructions;
        int n_instructions;
        if (about_open)
        {
            strcpy(title, STR_ABOUT);
            instructions = about_instructions_entries;
            drawAbout();
        }
        else
        {
            strcpy(title, (MAIN_TITLE));
            instructions = browser_instructions_entries;
            drawBrowser();
        }
        drawTopStatusBar(title);
        drawBottomStatusBar(instructions);
    }

    if (menu_open)
        drawMenu();
}

static void controlCommon()
{
    if (released_pad[PAD_PSBUTTON])
    {
        if (!isSkipPressedPsbutton())
        {
            if (about_open)
                exitAbout();
            else
                enterMenu();
        }
    }
}

void UiControlMain()
{
    if (menu_open)
    {
        ctrlMenu();
    }
    else
    {
        controlCommon();
        if (about_open)
            ctrlAbout();
        else
            ctrlBrowser();
    }
}

void UiMain()
{
    readPad();
    UiStartDrawing();
    UiDrawMain();
    UiEndDrawing();
    UiControlMain();
    unlockQuickMenu();
}
